﻿using movie.tool.library.hash;
using movie.tool.library.ui;
using movie.tool.library.utils;
using movie.tool.module.film.model;
using movie.tool.module.film.service;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace movie.tool.module.importer.ui
{
    /// <summary>
    /// ImportMoviePage.xaml 的交互逻辑
    /// </summary>
    public partial class ImportMoviePage : CommonPage
    {
        private MovieProject cfg;
        public MovieProject Config
        {
            get => cfg;
            set
            {
                cfg = value;
                SendPropertyChanged(nameof(Config));
            }
        }
        private BusyInfo busyInfo;
        public BusyInfo BusyInfo
        {
            get => busyInfo;
            set
            {
                busyInfo = value;
                SendPropertyChanged(nameof(BusyInfo));
            }
        }
        /// <summary>
        /// 当前编辑的剧本id
        /// </summary>
        public static long EditMovieId { get; set; }
        /// <summary>
        /// 导入时选择的剧本目录。在此目录下根据目录结构自动生成剧本的内容
        /// </summary>
        public static string MovieFolder { get; set; }
        public ImportMoviePage()
        {
            InitializeComponent();
            BusyInfo = new BusyInfo();
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                BusyInfo.Busy = true;
                MovieSynchronizer synchronizer = new MovieSynchronizer(BusyInfo, EditMovieId);
                this.Config = await synchronizer.Synchronise();
                this.Config.ImportProject = true;
                await LoadFromFolder();
            }
            finally
            {
                BusyInfo.Reset();
            }

        }
        private void MovieInfoControl_MovieTagsChanged(string[] obj)
        {
            if (Config != null && Config.Movie != null)
            {
                Config.Movie.Tag = obj;
            }
        }
        private void MovieInfoControl_NotifyMovieTagProperty()
        {
            if (Config != null && Config.Movie != null)
            {
                Config.Movie.NotifyTagsChanged();
            }
        }
        private Task LoadFromFolder()
        {
            return Task.Factory.StartNew(() => {
                LoadCover();
                LoadMovieAssist();
                LoadScenes();
                LoadClueCards();
                LoadPlayRoles();
                LoadChapterBook();
            });
        }

        private void LoadMovieAssist()
        {
            string assistPath = Path.Join(MovieFolder, "assist");
            if (Directory.Exists(assistPath))
            {
                IEnumerable<string> fs = Directory.GetFiles(assistPath).Where(item => item.EndsWith(".doc", true, null) || item.EndsWith(".docx", true, null)
                || item.EndsWith(".wps", true, null));
                if (fs != null && fs.Count() > 0)
                {
                    string rootPath = MovieService.ProjectJsonFilePath(Config.Id);
                    foreach (string file in fs)
                    {
                        string path = FileUtils.Copy(file, rootPath, false, "assist");
                        Config.Movie.Assist = Path.GetRelativePath(rootPath, path);
                        break;//只需要一个就可以了
                    }
                }
            }
        }

        /// <summary>
        /// 在选择的目录下,查找cover子目录,如果存在,则其下的图片文件就是封面文件
        /// </summary>
        private void LoadCover()
        {
            BusyInfo.BusyMessage = "正在导入封面...";
            string coverPath = Path.Join(MovieFolder, "cover");
            if (Directory.Exists(coverPath))
            {
                IEnumerable<string> files = Directory.GetFiles(coverPath)
                    .Where(item => item.EndsWith(".png", true, null) || item.EndsWith(".jpg", true, null)
                    || item.EndsWith(".jpeg", true, null) || item.EndsWith(".bmp", true, null));
                if (files != null && files.Count() > 0)
                {
                    string rootPath = MovieService.ProjectJsonFilePath(Config.Id);
                    string path = FileUtils.Copy(files.First(), rootPath, "cover");
                    string storePath = Path.GetRelativePath(rootPath, path);
                    Config.Movie.Cover = storePath;
                }
            }
        }
        /// <summary>
        /// 在选择的目录下,查找scene目录下的视频文件并生成SceneConfig
        /// </summary>
        private void LoadScenes()
        {
            string scenePath = Path.Join(MovieFolder, "scene");
            if (Directory.Exists(scenePath))
            {
                IEnumerable<string> files = Directory.GetFiles(scenePath)
                    .Where(item => item.EndsWith(".mp4", true, null));
                if (files != null && files.Count() > 0)
                {
                    if(Config.Scenes == null)
                    {
                        Config.Scenes = new ObservableCollection<SceneConfig>();
                    }
                    string rootPath = MovieService.ProjectJsonFilePath(Config.Id);
                    foreach (string file in files)
                    {
                        BusyInfo.BusyMessage = "正在导入剧幕文件:" + file;
                        string sceneName = "";
                        int sequence = 0;
                        MovieService.SceneNameAndSequence(Path.GetFileNameWithoutExtension(file), ref sceneName, ref sequence);
                        SceneConfig scene = null;
                        bool newScene = false;
                        if (sequence > 0)
                        {
                            scene = Config.FindScene(sequence);
                        }
                        if(scene == null)
                        {
                            scene = Config.FindScene(sceneName);
                        }
                        if(scene == null)
                        {
                            scene = new SceneConfig();
                            newScene = true;
                        }
                        scene.Name = sceneName;
                        if(sequence > 0)
                        {
                            scene.Sequence = sequence;
                        }
                        else
                        {
                            if (newScene)
                            {
                                scene.Sequence = Config.Scenes.Count > 0 ? Config.Scenes[Config.Scenes.Count - 1].Sequence + 1 : 1;
                            }
                        }
                        scene.PlayMode = 1;
                        if (file.StartsWith(rootPath))
                        {
                            //选择的文件在项目目录下,那就不用复制了
                            scene.File = Path.GetRelativePath(rootPath, file);
                        }
                        else
                        {
                            string path = Path.Combine(rootPath, "scene");
                            if (!Directory.Exists(path))
                            {
                                Directory.CreateDirectory(path);
                            }
                            path = Path.Combine(path, Path.GetFileName(file));
                            if (File.Exists(path))
                            {
                                string selectDigest = SHA1Hash.FileDigest(file);
                                string targetDigest = SHA1Hash.FileDigest(path);
                                if (!selectDigest.Equals(targetDigest))
                                {
                                    MessageBox.Show("文件" + path + "已经存在,无法复制,请选择不同名称的文件");
                                    return;
                                }
                                else
                                {
                                    //相同,不需要复制
                                    scene.File = Path.GetRelativePath(rootPath, path);
                                }
                            }
                            else
                            {
                                File.Copy(file, path);
                                scene.File = Path.GetRelativePath(rootPath, path);
                            }
                        }
                        if (newScene)
                        {
                            Dispatcher.Invoke(() => {
                                Config.Scenes.Add(scene);
                            });
                        }
                    }
                    Config.ResortScene();
                }
            }
        }
        /// <summary>
        /// 在选择的目录下,查找clue目录，此目录下以线索分组的名称创建目录，目录中以英文分号分隔的数字代表
        /// 分组所属剧幕的序号,序号数组与分组名称之前以下划线分隔。
        /// 如目录为“分组1_1;2;5;8”，代表分组名称为分组1,所属剧幕序号为[1,2,5,8]
        /// 分组目录下是线索的目录,分为高清目录hd,标清目录sd.
        /// hd和sd目录下是线索文件,png\jpg\jpeg\bmp类型文件为图片线索；mp4文件为视频线索;mp3文件为音频线索
        /// </summary>
        private void LoadClueCards()
        {
            string cluePath = Path.Join(MovieFolder, "clue");
            if (Directory.Exists(cluePath))
            {
                string[] dirs = Directory.GetDirectories(cluePath);
                if(dirs.Length > 0)
                {
                    if(Config.ClueCardGroups == null)
                    {
                        Config.ClueCardGroups = new ObservableCollection<ClueCardGroupConfig>();
                    }
                    foreach(string dir in dirs)
                    {
                        BusyInfo.BusyMessage = "正在处理线索目录:" + dir;
                        string name = Path.GetRelativePath(cluePath,dir);
                        ClueCardGroupConfig g = null;
                        string s = null;
                        string n = null;
                        string[] arr = name.Split("_");
                        if (arr.Length > 1)
                        {
                            n = arr[0];
                            s = arr[1];
                        }
                        else
                        {
                            n = name;
                        }
                        g = Config.FindGroup(n);
                        if(g == null)
                        {
                            g = new ClueCardGroupConfig();
                            g.Name = n;
                            Dispatcher.Invoke(() => {
                                Config.ClueCardGroups.Add(g);
                            });
                        }
                        if (!string.IsNullOrWhiteSpace(s))
                        {
                            g.Scenes = NumberUtils.StringToIntArray(s, ';');
                        }
                        LoadClueCards(g, dir,"sd");
                        LoadClueCards(g, dir, "hd");
                    }
                }
            }
        }
        /// <summary>
        /// 在dir目录下,查找线索文件,其中hd目录下为高清线索,sd目录下为标清线索
        /// </summary>
        /// <param name="g">线索分组</param>
        /// <param name="dir">搜索目录,为线索分组目录</param>
        private void LoadClueCards(ClueCardGroupConfig g, string dir,string subDir)
        {
            string sdPath = Path.Join(dir, subDir);
            if (Directory.Exists(sdPath))
            {
                string[] files = Directory.GetFiles(sdPath);
                IEnumerable<string> fs = files.Where(item => item.EndsWith(".png", true, null) || item.EndsWith(".jpg", true, null)
                    || item.EndsWith(".jpeg", true, null) || item.EndsWith(".bmp", true, null) || item.EndsWith(".mp4", true, null)
                    || item.EndsWith(".mp3", true, null));
                if(fs.Count() > 0)
                {
                    if(g.ClueCards == null)
                    {
                        g.ClueCards = new ObservableCollection<ClueCardConfig>();
                    }
                    string rootPath = MovieService.ProjectJsonFilePath(Config.Id);
                    foreach (string f in fs)
                    {
                        string name = Path.GetFileNameWithoutExtension(f);
                        ClueCardConfig clue = g.FindClueCard(name);
                        if(clue == null)
                        {
                            clue = new ClueCardConfig();
                            Dispatcher.Invoke(() => {
                                g.ClueCards.Add(clue);
                            });
                        }
                        clue.Type = f.EndsWith(".mp4", true, null) ? "vid" : f.EndsWith(".mp3", true, null) ? "aud" : "pic";
                        clue.Name = name;
                        clue.Group = g.Id;
                        string path = FileUtils.Copy(f, rootPath, false, "clue", subDir);
                        if ("sd".Equals(subDir))
                        {
                            clue.SdFile = Path.GetRelativePath(rootPath, path);
                        }
                        else
                        {
                            clue.HdFile = Path.GetRelativePath(rootPath, path);
                        }
                        
                    }
                }
            }
        }
        /// <summary>
        /// 在选择的目录下,查找roles目录。此目录下为角色目录,
        /// </summary>
        private void LoadPlayRoles()
        {
            string rolesPath = Path.Join(MovieFolder, "roles");
            if (Directory.Exists(rolesPath))
            {
                string[] files = Directory.GetFiles(rolesPath);
                IEnumerable<string> fs = files.Where(item => item.EndsWith(".png", true, null) || item.EndsWith(".jpg", true, null)
                    || item.EndsWith(".jpeg", true, null) || item.EndsWith(".bmp", true, null));
                if (fs.Count() > 0)
                {
                    string rootPath = MovieService.ProjectJsonFilePath(Config.Id);
                    if (Config.Roles == null)
                    {
                        Config.Roles = new ObservableCollection<PlayerRoleConfig>();
                    }
                    foreach (string filePath in fs)
                    {
                        BusyInfo.BusyMessage = "正在处理角色文件:" + filePath;
                        string fileName = Path.GetFileNameWithoutExtension(filePath);
                        PlayerRoleConfig role = null;
                        string[] arr = fileName.Split("_");
                        if (arr.Length > 0)
                        {
                            role = Config.FindRole(arr[0]);
                            if (role == null)
                            {
                                role = new PlayerRoleConfig();
                                role.Name = arr[0];
                                role.Gender = "男";
                                role.CrossGender = "不可";
                                Dispatcher.Invoke(() => {
                                    Config.Roles.Add(role);
                                });
                            }
                        }
                        if (arr.Length > 1)
                        {
                            string gender = arr[1];
                            if ("男".Equals(gender) || "女".Equals(gender))
                            {
                                role.Gender = gender;
                            }
                        }
                        if (arr.Length > 2)
                        {
                            string cross = arr[2];
                            if ("可".Equals(cross) || "不可".Equals(cross))
                            {
                                role.CrossGender = cross;
                            }
                        }
                        string path = FileUtils.Copy(filePath, rootPath, false, "roles");
                        role.FilePath = Path.GetRelativePath(rootPath, path);
                    }
                }
            }
        }
        /// <summary>
        /// 在选择的目录下,查找books目录加载章节和对应的电子书。需要在加载角色之后
        /// </summary>
        private void LoadChapterBook()
        {
            string booksPath = Path.Join(MovieFolder, "books");
            if (Directory.Exists(booksPath))
            {
                IEnumerable<string> dirs = Directory.GetDirectories(booksPath);
                if (dirs != null && dirs.Count() > 0)
                {
                    if (Config.Chapters == null)
                    {
                        Config.Chapters = new ObservableCollection<BookChapter>();
                    }
                    foreach (string dir in dirs)
                    {
                        BusyInfo.BusyMessage = "正在处理电子书目录:" + dir;
                        string chapterName = "";
                        int sequence = 0;
                        MovieService.SceneNameAndSequence(Path.GetRelativePath(booksPath, dir), ref chapterName, ref sequence);
                        BookChapter chapter = null;
                        bool newItem = false;
                        if (sequence > 0)
                        {
                            chapter = Config.FindChapter(sequence);
                        }
                        if (chapter == null)
                        {
                            chapter = Config.FindChapter(chapterName);
                        }
                        if (chapter == null)
                        {
                            chapter = new BookChapter();
                            newItem = true;
                        }
                        chapter.Name = chapterName;
                        if (sequence > 0)
                        {
                            chapter.Sequence = sequence;
                        }
                        else
                        {
                            chapter.Sequence = Config.Chapters.Count > 0 ? Config.Chapters[Config.Chapters.Count - 1].Sequence + 1 : 1;
                        }
                        if (newItem)
                        {
                            Dispatcher.Invoke(() => {
                                Config.Chapters.Add(chapter);
                            });
                        }
                        LoadRoleBook(chapter,dir);
                    }
                    Config.ResortChapter();
                }
            }
        }
        /// <summary>
        /// 加载章节对应的角色电子书
        /// </summary>
        /// <param name="chapter">章节对象</param>
        /// <param name="dir">电子书搜索目录,为章节目录</param>
        private void LoadRoleBook(BookChapter chapter, string dir)
        {
            if (!Directory.Exists(dir))
            {
                return;
            }
            IEnumerable<string> fs = Directory.GetFiles(dir).Where(item => item.EndsWith(".doc", true, null) || item.EndsWith(".docx", true, null)
                || item.EndsWith(".wps", true, null));
            if(fs != null && fs.Count() > 0)
            {
                if(Config.Books == null)
                {
                    Config.Books = new ObservableCollection<PlayRoleBookConfig>();
                }
                string rootPath = MovieService.ProjectJsonFilePath(Config.Id);
                foreach (string file in fs)
                {
                    string name = Path.GetFileNameWithoutExtension(file);
                    PlayerRoleConfig role = Config.FindRole(name);
                    if(role == null)
                    {
                        throw new ApplicationException("名称为" + name + "的角色未找到");
                    }
                    PlayRoleBookConfig book = Config.FindBook(name, chapter.Name);
                    if(book == null)
                    {
                        if(role.Id > 0 && chapter.Id > 0)
                        {
                            book = Config.FindBook(role.Id, chapter.Id);
                        }
                    }
                    if(book == null)
                    {
                        book = new PlayRoleBookConfig();
                        book.Name = chapter.Name;
                        book.RoleName = name;
                        Dispatcher.Invoke(() => {
                            Config.Books.Add(book);
                        });
                    }
                    string path = FileUtils.Copy(file, rootPath, false, "books", chapter.Name);
                    book.FilePath = Path.GetRelativePath(rootPath, path);
                }
            }
        }

        private void ReturnClick(object sender, RoutedEventArgs e)
        {
            MainWindow.ShowPage("/module/film/ui/MovieListPage.xaml");
        }
    }
}
